package com.tpshion.chat.websocket;

import com.tpshion.chat.domain.model.MessageModel;
import com.tpshion.chat.domain.model.MessageType;
import com.tpshion.chat.exception.MyException;
import com.tpshion.chat.utils.JsonUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: 处理文本消息类
 * @Author: tpshion
 * @Date: 2020/5/18 19:04
 * @Version: 1.0
 */
@Slf4j
public class TextServeHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static ConcurrentHashMap<String, Channel> clients = WebSocketServer.clients;

    private static ConcurrentHashMap<Channel,List<MessageModel>> userMsg = WebSocketServer.userMsg;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //连接成功处理
        if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete){
            MessageModel messageModel = new MessageModel();
            messageModel.setType(MessageType.CONN.getType());
            messageModel.setData("ws服务连接成功");
            log.info("用户连接服务，当前在线人数："+ clients.size());
            ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.obj2String(messageModel)));
            /**
             * 发送未读消息
             */
            userMsg.forEach((key,vaule) ->{
                if(key == ctx.channel()){
                    vaule.forEach(item ->{
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.obj2String(item)));
                    });
                    userMsg.remove(key);
                }
            });
        }

        //连接读写空闲处理
        if(evt instanceof IdleStateEvent){
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.ALL_IDLE) {
                log.info("读写空闲。。。。。");
                // 关闭无用channel，以防资源浪费
                ctx.channel().close();
            }
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        String text = textWebSocketFrame.text();
        log.info("收到客户端消息："+text);
    }

    /**
     * 用户退出处理
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        clients.forEach((key,value) ->{
            if(value.equals(ctx.channel())){
                clients.remove(key);
            }
        });
        log.info("用户退出服务，当前在线人数：" + clients.size());
    }

    /**
     * 连接异常处理
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if(cause instanceof MyException){
            log.info("websocket 连接权限验证不通过");
        }else{
            log.error("channel异常："+cause.getMessage());
        }
    }
}
